package com.ruoyi.web.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;


public class HttpClientUtil {

    // utf-8字符编码
    public static final String CHARSET_UTF_8 = "utf-8";

    // HTTP内容类型。
    public static final String CONTENT_TYPE_TEXT_HTML = "text/xml";

    // HTTP内容类型。相当于form表单的形式，提交数据
    public static final String CONTENT_TYPE_FORM_URL = "application/x-www-form-urlencoded";

    // HTTP内容类型。相当于form表单的形式，提交数据
    public static final String CONTENT_TYPE_JSON_URL = "application/json;charset=utf-8";


    // 连接管理器
    private static PoolingHttpClientConnectionManager pool;

    // 请求配置
    private static RequestConfig requestConfig;

    static {

        try {
            //System.out.println("初始化HttpClientTest~~~开始");
            SSLContextBuilder builder = new SSLContextBuilder();
            builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    builder.build());
            // 配置同时支持 HTTP 和 HTPPS
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create().register(
                    "http", PlainConnectionSocketFactory.getSocketFactory()).register(
                    "https", sslsf).build();
            // 初始化连接管理器
            pool = new PoolingHttpClientConnectionManager(
                    socketFactoryRegistry);
            // 将最大连接数增加到200，实际项目最好从配置文件中读取这个值
            pool.setMaxTotal(200);
            // 设置最大路由
            pool.setDefaultMaxPerRoute(2);
            // 根据默认超时限制初始化requestConfig
            int socketTimeout = 30000000;
            int connectTimeout = 30000000;
            int connectionRequestTimeout = 30000000;
            requestConfig = RequestConfig.custom().setConnectionRequestTimeout(
                    connectionRequestTimeout).setSocketTimeout(socketTimeout).setConnectTimeout(
                    connectTimeout).build();

            //System.out.println("初始化HttpClientTest~~~结束");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }


        // 设置请求超时时间
//        requestConfig = RequestConfig.custom().setSocketTimeout(30000000).setConnectTimeout(30000000)
//                .setConnectionRequestTimeout(30000000).build();
    }

    public static CloseableHttpClient getHttpClient() {

        CloseableHttpClient httpClient = HttpClients.custom()
                // 设置连接池管理
                .setConnectionManager(pool)
                // 设置请求配置
                .setDefaultRequestConfig(requestConfig)
                // 设置重试次数
                .setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))
                .build();

        return httpClient;
    }

    /**
     * 发送Get请求
     *
     * @return
     */
    public static String sendHttpGetNew(String url, Integer isProxy, String hostname, int port) {

        // 响应内容
        String responseContent = null;
        CloseableHttpResponse response = null;
        try {
            Random rand = new Random();
            int sleepTime = rand.nextInt(2000) + 1;
            Thread.sleep(sleepTime);

            // 设置SSLContext
            SSLContext ssl = createIgnoreVerifySSL();
            DefaultProxyRoutePlanner routePlanner = null;
            if (isProxy == 1) {
                //创建代理地址
                HttpHost proxy = new HttpHost(hostname, port);
                routePlanner = new DefaultProxyRoutePlanner(proxy);
            }
            CloseableHttpClient httpClient = null;
            if (url.startsWith("https://")) {
                // 设置协议http和https对应的处理socket链接工厂的对象
                Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                        .register("http", PlainConnectionSocketFactory.INSTANCE)
                        .register("https", new SSLConnectionSocketFactory(ssl, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER))
                        .build();
                PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
                HttpClientBuilder builder = HttpClients.custom();
                builder.setConnectionManager(connManager).setSSLContext(ssl);
                if (isProxy == 1) {
                    builder.setRoutePlanner(routePlanner);
                }
                httpClient = builder.build();
                //            httpClient = HttpClients.custom()
                //                    .setRoutePlanner(routePlanner)
                //                    .setSSLContext(ssl)
                //                    .build();
            } else {
                HttpClientBuilder builder = HttpClients.custom();
                builder.setSSLContext(ssl);
                if (isProxy == 1) {
                    builder.setRoutePlanner(routePlanner);
                }
                httpClient = builder.build();
                //            httpClient = HttpClients.custom()
                //                    .setRoutePlanner(routePlanner)
                //                    .setSSLContext(ssl)
                //                    .build();
            }
            // 创建HttpContext以保持会话状态
            HttpClientContext context = HttpClientContext.create();

            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader("User-Agent",
                    "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36");
            httpGet.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");
            httpGet.setHeader("Accept-Encoding", "gzip, deflate");
            httpGet.setHeader("Accept-Language", "en-US,en;q=0.5");
            //构建超时等配置信息
            RequestConfig config = RequestConfig.custom()
                    .setConnectTimeout(120000) //连接超时时间
                    .setConnectionRequestTimeout(120000) //从连接池中取的连接的最长时间
                    .setSocketTimeout(120000) //数据传输的超时时间
                    .build();
            //设置请求配置时间
            httpGet.setConfig(config);
            // 执行请求
            response = httpClient.execute(httpGet, context);
            // 得到响应实例
            HttpEntity entity = response.getEntity();
            if (response.getStatusLine().getStatusCode() == 301) {
                String redirectUrl = response.getHeaders("Location")[0].getValue();
            }

            // 判断响应状态
            if (response.getStatusLine().getStatusCode() >= 300) {
                throw new Exception(
                        "HTTP Request is not success, Response code is " + response.getStatusLine().getStatusCode());
            }

            if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {
                responseContent = EntityUtils.toString(entity, CHARSET_UTF_8);
                EntityUtils.consume(entity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // 释放资源
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseContent;
    }

    /**
     * 发送Post请求
     *
     * @param url
     * @return
     */
    public static String sendHttpPostNew(String url, String paramsJson, Integer isProxy, String hostname, int port) {
        // 响应内容
        String responseContent = null;
        CloseableHttpResponse response = null;
        try {
            Random rand = new Random();
            int sleepTime = rand.nextInt(2000) + 1;
            Thread.sleep(sleepTime);

            // 设置SSLContext
            SSLContext ssl = createIgnoreVerifySSL();
            DefaultProxyRoutePlanner routePlanner = null;
            if (isProxy == 1) {
                //创建代理地址
                HttpHost proxy = new HttpHost(hostname, port);
                routePlanner = new DefaultProxyRoutePlanner(proxy);
            }
            CloseableHttpClient httpClient = null;
            if (url.startsWith("https://")) {
                // 设置协议http和https对应的处理socket链接工厂的对象
                Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                        .register("http", PlainConnectionSocketFactory.INSTANCE)
                        .register("https", new SSLConnectionSocketFactory(ssl, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER))
                        .build();
                PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
                HttpClientBuilder builder = HttpClients.custom();
                builder.setConnectionManager(connManager).setSSLContext(ssl);
                if (isProxy == 1) {
                    builder.setRoutePlanner(routePlanner);
                }
                httpClient = builder.build();
    //            httpClient = HttpClients.custom()
    //                    .setRoutePlanner(routePlanner)
    //                    .setSSLContext(ssl)
    //                    .build();
            } else {
                HttpClientBuilder builder = HttpClients.custom();
                builder.setSSLContext(ssl);
                if (isProxy == 1) {
                    builder.setRoutePlanner(routePlanner);
                }
                httpClient = builder.build();
    //            httpClient = HttpClients.custom()
    //                    .setRoutePlanner(routePlanner)
    //                    .setSSLContext(ssl)
    //                    .build();
            }
            // 创建HttpContext以保持会话状态
            HttpClientContext context = HttpClientContext.create();

            HttpPost httpPost = new HttpPost(url);
            // 设置参数
            if (paramsJson != null && paramsJson.trim().length() > 0) {
                StringEntity stringEntity = new StringEntity(paramsJson, "UTF-8");
                stringEntity.setContentType(CONTENT_TYPE_JSON_URL);
                httpPost.setEntity(stringEntity);
            }
            httpPost.setHeader("User-Agent",
                    "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36");
            httpPost.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");
            httpPost.setHeader("Accept-Encoding", "gzip, deflate");
            httpPost.setHeader("Accept-Language", "en-US,en;q=0.5");
            //构建超时等配置信息
            RequestConfig config = RequestConfig.custom()
                    .setConnectTimeout(120000) //连接超时时间
                    .setConnectionRequestTimeout(120000) //从连接池中取的连接的最长时间
                    .setSocketTimeout(120000) //数据传输的超时时间
                    .build();
            //设置请求配置时间
            httpPost.setConfig(config);
            // 执行请求
            response = httpClient.execute(httpPost, context);
            // 得到响应实例
            HttpEntity entity = response.getEntity();
            if (response.getStatusLine().getStatusCode() == 301) {
                String redirectUrl = response.getHeaders("Location")[0].getValue();

            }

            // 判断响应状态
            if (response.getStatusLine().getStatusCode() >= 300) {
                throw new Exception(
                        "HTTP Request is not success, Response code is " + response.getStatusLine().getStatusCode());
            }

            if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {
                responseContent = EntityUtils.toString(entity, CHARSET_UTF_8);
                EntityUtils.consume(entity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // 释放资源
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseContent;

    }

    /**
     * 发送Post请求
     *
     * @param httpPost
     * @return
     */
    private static String sendHttpPost(HttpPost httpPost) {

        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        // 响应内容
        String responseContent = null;
        try {
            // 创建默认的httpClient实例.
            httpClient = getHttpClient();
            // 配置请求信息
            httpPost.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpPost);
            // 得到响应实例
            HttpEntity entity = response.getEntity();
            // 可以获得响应头
            // Header[] headers = response.getHeaders(HttpHeaders.CONTENT_TYPE);
            // for (Header header : headers) {
            // System.out.println(header.getName());
            // }

            // 得到响应类型
            // System.out.println(ContentType.getOrDefault(response.getEntity()).getMimeType());

            // 判断响应状态
            if (response.getStatusLine().getStatusCode() >= 300) {
                throw new Exception(
                        "HTTP Request is not success, Response code is " + response.getStatusLine().getStatusCode());
            }

            if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {
                responseContent = EntityUtils.toString(entity, CHARSET_UTF_8);
                EntityUtils.consume(entity);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // 释放资源
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseContent;
    }

    /**
     * 发送Get请求
     *
     * @param httpGet
     * @return
     */
    private static String sendHttpGet(HttpGet httpGet) {

        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        // 响应内容
        String responseContent = null;
        try {
            // 创建默认的httpClient实例.
            httpClient = getHttpClient();
            // 配置请求信息
            httpGet.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpGet);
            // 得到响应实例
            HttpEntity entity = response.getEntity();

            // 可以获得响应头
            // Header[] headers = response.getHeaders(HttpHeaders.CONTENT_TYPE);
            // for (Header header : headers) {
            // System.out.println(header.getName());
            // }

            // 得到响应类型
            // System.out.println(ContentType.getOrDefault(response.getEntity()).getMimeType());

            // 判断响应状态
            if (response.getStatusLine().getStatusCode() >= 300) {
                throw new Exception(
                        "HTTP Request is not success, Response code is " + response.getStatusLine().getStatusCode());
            }

            if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {
                responseContent = EntityUtils.toString(entity, CHARSET_UTF_8);
                EntityUtils.consume(entity);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // 释放资源
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseContent;
    }



    /**
     * 发送 post请求
     *
     * @param httpUrl
     *      地址
     */
    public static String sendHttpPost(String httpUrl) {
        // 创建httpPost
        HttpPost httpPost = new HttpPost(httpUrl);
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 get请求
     *
     * @param httpUrl
     */
    public static String sendHttpGet(String httpUrl) {
        // 创建get请求
        HttpGet httpGet = new HttpGet(httpUrl);
        return sendHttpGet(httpGet);
    }



    /**
     * 发送 post请求（带文件）
     *
     * @param httpUrl
     *      地址
     * @param maps
     *      参数
     * @param fileLists
     *      附件
     */
//    public static String sendHttpPost(String httpUrl, Map<String, String> maps, List<File> fileLists) {
//        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
//        MultipartEntityBuilder meBuilder = MultipartEntityBuilder.create();
//        if (maps != null) {
//            for (String key : maps.keySet()) {
//                meBuilder.addPart(key, new StringBody(maps.get(key), ContentType.TEXT_PLAIN));
//            }
//        }
//        if (fileLists != null) {
//            for (File file : fileLists) {
//                FileBody fileBody = new FileBody(file);
//                meBuilder.addPart("files", fileBody);
//            }
//        }
//        HttpEntity reqEntity = meBuilder.build();
//        httpPost.setEntity(reqEntity);
//        return sendHttpPost(httpPost);
//    }

    /**
     * 发送 post请求
     *
     * @param httpUrl
     *      地址
     * @param params
     *      参数(格式:key1=value1&key2=value2)
     *
     */
    public static String sendHttpPost(String httpUrl, String params) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        try {
            // 设置参数
            if (params != null && params.trim().length() > 0) {
                StringEntity stringEntity = new StringEntity(params, "UTF-8");
                stringEntity.setContentType(CONTENT_TYPE_FORM_URL);
                httpPost.setEntity(stringEntity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 post请求
     *
     * @param maps
     *      参数
     */
    public static String sendHttpPost(String httpUrl, Map<String, String> maps) {
        String parem = convertStringParamter(maps);
        return sendHttpPost(httpUrl, parem);
    }


    /**
     * 发送 post请求 发送json数据
     *
     * @param httpUrl
     *      地址
     * @param paramsJson
     *      参数(格式 json)
     *
     */
    public static String sendHttpPostJson(String httpUrl, String paramsJson) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        try {
            // 设置参数
            if (paramsJson != null && paramsJson.trim().length() > 0) {
                StringEntity stringEntity = new StringEntity(paramsJson, "UTF-8");
                stringEntity.setContentType(CONTENT_TYPE_JSON_URL);
                httpPost.setEntity(stringEntity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sendHttpPost(httpPost);
    }

    /**
     * 发送 post请求 发送xml数据
     *
     * @param httpUrl  地址
     * @param paramsXml 参数(格式 Xml)
     *
     */
    public static String sendHttpPostXml(String httpUrl, String paramsXml) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        try {
            // 设置参数
            if (paramsXml != null && paramsXml.trim().length() > 0) {
                StringEntity stringEntity = new StringEntity(paramsXml, "UTF-8");
                stringEntity.setContentType(CONTENT_TYPE_TEXT_HTML);
                httpPost.setEntity(stringEntity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sendHttpPost(httpPost);
    }


    /**
     * 将map集合的键值对转化成：key1=value1&key2=value2 的形式
     *
     * @param parameterMap
     *      需要转化的键值对集合
     * @return 字符串
     */
    public static String convertStringParamter(Map parameterMap) {
        StringBuffer parameterBuffer = new StringBuffer();
        if (parameterMap != null) {
            Iterator iterator = parameterMap.keySet().iterator();
            String key = null;
            String value = null;
            while (iterator.hasNext()) {
                key = (String) iterator.next();
                if (parameterMap.get(key) != null) {
                    value = (String) parameterMap.get(key);
                } else {
                    value = "";
                }
                parameterBuffer.append(key).append("=").append(value);
                if (iterator.hasNext()) {
                    parameterBuffer.append("&");
                }
            }
        }
        return parameterBuffer.toString();
    }

    public static SSLContext createIgnoreVerifySSL() {
        SSLContext sc = null;
        try {
//            sc = new SSLContextBuilder().loadTrustMaterial(null,
//                    (TrustStrategy) (X509Certificate[] arg0, String arg1) -> true).build();
            sc = SSLContext.getInstance("TLS");
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 实现一个X509TrustManager接口，用于绕过验证，即信任所有证书
        X509TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(
                    java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(
                    java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };

        try {
            sc.init(null, new TrustManager[] { trustManager }, null);
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return sc;
    }



    public static void main(String[] args){
        String result=sendHttpGet("http://192.168.3.144:8383/jcxwyc?filePath=http://10.16.4.189:10089/systemFilePath/90b84f52a90e9f54e8472b99a1713a3.png");
        System.out.println(result);
        JSONObject jsonObject = JSON.parseObject(result);
        JSONObject data = jsonObject.getJSONObject("data");
        String imgpath = data.getString("imgpath");
        String dataList = data.getString("dataList");
        JSONArray array = data.getJSONArray("dataList");
        String results = "";
        for (int i = 0; i < array.size(); i++) {
            JSONObject names = JSON.parseObject(array.getString(i));
            String name = names.getString("name");
            String count = names.getString("count");
            results += name + count + "个,";
        }
        if (StringUtils.isNotBlank(results)) {
            results = results.substring(0, results.length() - 1);
        }
        System.out.println("imgpath=" + imgpath + ";dataList=" + dataList);
        System.out.println("results=" + results);
    }
}
